package org.jeecg.modules.demo.pcl.controller;

import java.util.*;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.demo.pcl.entity.RestfulAsrsSerachLog;
import org.jeecg.modules.demo.pcl.service.IRestfulAsrsSerachLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.*;
import java.util.Date;

/**
 * @Description: RestFul接口-Mes-ASRS
 */
@Api(tags = "RestFul接口-Mes-ASRS")
@RestController
@RequestMapping("/rest/asrs")
@Slf4j
public class RestfulAsrsController {

    @Autowired
    private IRestfulAsrsSerachLogService restfulAsrsSerachLogService;

    private static final String DB_URL = "jdbc:as400://10.224.80.16;naming=system;libraries=S78AF550;translate binary=true;";
    private static final String USER = "Hand_mes";
    private static final String PASSWORD = "Hand_mes@";

    private static final String SQL_QUERY =
            "SELECT\n" +
                    "    TRIM(s.HTPART) AS materialcode,\n" +
                    "    TRIM(s.HTLOTN) AS batchcode,\n" +
                    "    s.HTQTY - s.HTQTYC AS number,\n" +
                    "    VARCHAR_FORMAT(l.PCDATE, 'YYYY-MM-DD') || ' ' ||\n" +
                    "    SUBSTR(CHAR(LPAD(l.PCTIMC, 6, '0')), 1, 2) || ':' || \n" +
                    "    SUBSTR(CHAR(LPAD(l.PCTIMC, 6, '0')), 3, 2) || ':' || \n" +
                    "    SUBSTR(CHAR(LPAD(l.PCTIMC, 6, '0')), 5, 2) AS createtime,\n" +
                    "    TRIM(l.PCFUT8) AS \"desc\"\n" +
                    "FROM\n" +
                    "    CHCDAT.SERI s\n" +
                    "    JOIN CHCDAT.LBDT l ON l.\"PCSER#\" = s.HTSERN\n" +
                    "WHERE\n" +
                    "    s.HTSERN = ?";

    private static final String SQL_QUERY_2 =
            "SELECT\n" +
                    "    TRIM(s.HTPART) AS materialcode,\n" +
                    "    TRIM(s.HTLOTN) AS batchcode,\n" +
                    "    s.HTQTY - s.HTQTYC AS number,\n" +
                    "    VARCHAR_FORMAT(l.PCDATE, 'YYYY-MM-DD') || ' ' ||\n" +
                    "    SUBSTR(CHAR(LPAD(l.PCTIMC, 6, '0')), 1, 2) || ':' || \n" +
                    "    SUBSTR(CHAR(LPAD(l.PCTIMC, 6, '0')), 3, 2) || ':' || \n" +
                    "    SUBSTR(CHAR(LPAD(l.PCTIMC, 6, '0')), 5, 2) AS createtime,\n" +
                    "    TRIM(l.PCFUT8) AS \"desc\"\n" +
                    "FROM\n" +
                    "    CHCCASTING.SERI s\n" +
                    "    JOIN CHCCASTING.LBDT l ON l.\"PCSER#\" = s.HTSERN\n" +
                    "WHERE\n" +
                    "    s.HTSERN = ?";

    /**
     * Gree-ASRS 标签号查询零件号接口
     */
    @ApiOperation(value = "Gree-ASRS 标签号查询零件号接口", notes = "Gree-ASRS 标签号查询零件号接口")
    @PostMapping(value = "/barinfo")
    public Response query(@RequestBody RequestData requestData, HttpServletRequest request) throws IOException {
        // 设置默认时区为本地时区
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

        // 获取客户端 IP 地址
        String ipAddress = getClientIP(request);

        // 参数校验
        if (requestData == null || requestData.getBarinfo() == null || requestData.getBarinfo().trim().isEmpty()) {
            logAndSaveCall(requestData, null, "error", "条码信息不能为空", ipAddress);
            return new Response("error", "条码信息不能为空", null);
        }

        try {
            Class.forName("com.ibm.as400.access.AS400JDBCDriver");
        } catch (ClassNotFoundException e) {
            log.error("JDBC 驱动加载失败", e);
            logAndSaveCall(requestData, null, "error", e.getMessage(), ipAddress);
            return new Response("error", "JDBC 驱动加载失败: " + e.getMessage(), null);
        }

        try (Connection connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);
             PreparedStatement pst = connection.prepareStatement(SQL_QUERY)) {

            pst.setString(1, requestData.getBarinfo());
            ResultSet rs = pst.executeQuery();

            if (rs.next()) {
                ResponseData data = new ResponseData(
                        rs.getString("materialcode"),
                        rs.getString("batchcode"),
                        rs.getInt("number"),
                        rs.getString("createtime"),
                        rs.getString("desc")
                );
                logAndSaveCall(requestData, data, "success", null, ipAddress);
                return new Response("success", "查询成功！", data);
            } else {
                logAndSaveCall(requestData, null, "error", "未找到对应的记录！", ipAddress);
                return new Response("error", "未找到对应的记录！", null);
            }
        } catch (SQLException e) {
            log.error("数据库查询失败", e);
            logAndSaveCall(requestData, null, "error", e.getMessage(), ipAddress);
            return new Response("error", "数据库查询失败: " + e.getMessage(), null);
        }
    }
    /**
     * Gree-ASRS 标签号查询零件号接口
     */
    @ApiOperation(value = "Gree-ASRS 标签号查询零件号接口", notes = "Gree-ASRS 标签号查询零件号接口")
    @PostMapping(value = "/barinfoV2")
    public Response query2(@RequestBody RequestData requestData, HttpServletRequest request) throws IOException {
        // 设置默认时区为本地时区
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

        // 获取客户端 IP 地址
        String ipAddress = getClientIP(request);

        // 参数校验
        if (requestData == null || requestData.getBarinfo() == null || requestData.getBarinfo().trim().isEmpty()) {
            logAndSaveCall(requestData, null, "error", "条码信息不能为空", ipAddress);
            return new Response("error", "条码信息不能为空", null);
        }

        try {
            Class.forName("com.ibm.as400.access.AS400JDBCDriver");
        } catch (ClassNotFoundException e) {
            log.error("JDBC 驱动加载失败", e);
            logAndSaveCall(requestData, null, "error", e.getMessage(), ipAddress);
            return new Response("error", "JDBC 驱动加载失败: " + e.getMessage(), null);
        }

        try (Connection connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);
             PreparedStatement pst = connection.prepareStatement(SQL_QUERY_2)) {

            pst.setString(1, requestData.getBarinfo());
            ResultSet rs = pst.executeQuery();

            if (rs.next()) {
                ResponseData data = new ResponseData(
                        rs.getString("materialcode"),
                        rs.getString("batchcode"),
                        rs.getInt("number"),
                        rs.getString("createtime"),
                        rs.getString("desc")
                );
                logAndSaveCall(requestData, data, "success", null, ipAddress);
                return new Response("success", "查询成功！", data);
            } else {
                logAndSaveCall(requestData, null, "error", "未找到对应的记录！", ipAddress);
                return new Response("error", "未找到对应的记录！", null);
            }
        } catch (SQLException e) {
            log.error("数据库查询失败", e);
            logAndSaveCall(requestData, null, "error", e.getMessage(), ipAddress);
            return new Response("error", "数据库查询失败: " + e.getMessage(), null);
        }
    }

    /**
     * Gree-ASRS 零件号查MinMax批量接口
     */
    @ApiOperation(value = "Gree-ASRS 零件号查MinMax批量接口", notes = "Gree-ASRS 零件号查MinMax批量接口")
    @PostMapping(value = "/getminmaxbatch")
    public BatchMinMaxResponse getminmaxbatch(@RequestBody BatchMinMaxRequestData requestData, HttpServletRequest request) throws IOException {
        // 设置默认时区为本地时区
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
        // 获取客户端 IP 地址
        String ipAddress = getClientIP(request);
        // 参数校验
        if (requestData == null || requestData.getBarinfolist() == null || requestData.getBarinfolist().isEmpty()) {
            logAndSaveCallBatch(requestData, null, "error", "零件号List不能为空", ipAddress);
            return new BatchMinMaxResponse("error", "零件号List不能为空", null);
        }
        try {
            Class.forName("com.ibm.as400.access.AS400JDBCDriver");
        } catch (ClassNotFoundException e) {
            log.error("JDBC 驱动加载失败", e);
            logAndSaveCallBatch(requestData, null, "error", e.getMessage(), ipAddress);
            return new BatchMinMaxResponse("error", "JDBC 驱动加载失败: " + e.getMessage(), null);
        }

        // 更新SQL查询
        String sqlQuery = "SELECT TRIM(s.AVPART) AS AVPART, TRIM(s.AVDES1) AS AVDES1, " +
                "s2.V6MAXQ, s2.V6MINQ, s2.V6MPCK, COALESCE(s2.V6PCTR, '') AS V6PCTR, TRIM(p.JODES1) AS JODES1 " +
                "FROM CHCDAT.STKMM s " +
                "LEFT JOIN CHCDAT.STKA s2 ON s2.V6PART = s.AVPART " +
                "LEFT JOIN CHCDAT.POPRJ p ON TRIM(p.\"JOPRJ#\") = 'E' || SUBSTR(s.AVPART, 3, 2) " +
                "WHERE s.AVPART IN (" +
                String.join(",", Collections.nCopies(requestData.getBarinfolist().size(), "?")) + ") " +
                "UNION ALL " +
                "SELECT TRIM(s.AVPART) AS AVPART, TRIM(s.AVDES1) AS AVDES1, " +
                "s2.V6MAXQ, s2.V6MINQ, s2.V6MPCK, COALESCE(s2.V6PCTR, '') AS V6PCTR, TRIM(p.JODES1) AS JODES1 " +
                "FROM CHCCASTING.STKMM s " +
                "LEFT JOIN CHCDAT.STKA s2 ON s2.V6PART = s.AVPART " +
                "LEFT JOIN CHCDAT.POPRJ p ON TRIM(p.\"JOPRJ#\") = 'E' || SUBSTR(s.AVPART, 3, 2) " +
                "WHERE s.AVPART IN (" +
                String.join(",", Collections.nCopies(requestData.getBarinfolist().size(), "?")) + ")";

        try (Connection connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);
             PreparedStatement pst = connection.prepareStatement(sqlQuery)) {
            // Set parameters for both IN clauses (need to set twice the number of parameters)
            for (int i = 0; i < requestData.getBarinfolist().size(); i++) {
                pst.setString(i + 1, requestData.getBarinfolist().get(i));
            }
            for (int i = 0; i < requestData.getBarinfolist().size(); i++) {
                pst.setString(i + 1 + requestData.getBarinfolist().size(), requestData.getBarinfolist().get(i));
            }
            ResultSet rs = pst.executeQuery();
            List<BatchMinMaxResponseData> dataList = new ArrayList<>();
            while (rs.next()) {
                BatchMinMaxResponseData data = new BatchMinMaxResponseData(
                        rs.getString("AVPART"),
                        rs.getString("AVDES1"),
                        rs.getObject("V6MAXQ") != null ? rs.getInt("V6MAXQ") : 0,
                        rs.getObject("V6MINQ") != null ? rs.getInt("V6MINQ") : 0,
                        rs.getObject("V6MPCK") != null ? rs.getInt("V6MPCK") : 0,
                        rs.getString("V6PCTR"),
                        rs.getString("JODES1") // TRIM后的项目描述字段
                );
                dataList.add(data);
            }
            if (!dataList.isEmpty()) {
                logAndSaveCallBatch(requestData, dataList, "success", null, ipAddress);
                return new BatchMinMaxResponse("success", "查询成功！", dataList);
            } else {
                logAndSaveCallBatch(requestData, null, "error", "未找到对应的记录！", ipAddress);
                return new BatchMinMaxResponse("error", "未找到对应的记录！", null);
            }
        } catch (SQLException e) {
            log.error("数据库查询失败", e);
            logAndSaveCallBatch(requestData, null, "error", e.getMessage(), ipAddress);
            return new BatchMinMaxResponse("error", "数据库查询失败: " + e.getMessage(), null);
        }
    }


    private void logAndSaveCall(RequestData requestData, ResponseData responseData,
                                String status, String errorMsg,
                                String ipAddress) {
        try {
            RestfulAsrsSerachLog logEntry = new RestfulAsrsSerachLog();
            logEntry.setRequestTime(new Date());
            logEntry.setBarinfo(requestData.getBarinfo());
            logEntry.setStatus(status);

            // 拼接 IP 和 User-Agent 到 successMessage 或 errorMessage
            String clientInfo = String.format("IP: %s", ipAddress);

            if ("success".equalsIgnoreCase(status)) {
                logEntry.setSuccessMessage("查询成功。" + clientInfo);
                if (responseData != null) {
                    logEntry.setMaterialcode(responseData.getMaterialcode());
                }
                logEntry.setErrorMessage(null); // 清空错误信息
            } else {
                logEntry.setSuccessMessage(null); // 错误时不设置成功信息
                logEntry.setErrorMessage(errorMsg + " [" + clientInfo + "]");
            }

            // 使用 service 插入日志
            restfulAsrsSerachLogService.save(logEntry);
        } catch (Exception e) {
            log.error("保存调用日志失败", e);
        }
    }

    private void logAndSaveCallBatch(BatchMinMaxRequestData requestData, List<BatchMinMaxResponseData> responseDataList,
                                     String status, String errorMsg, String ipAddress) {
        try {
            RestfulAsrsSerachLog logEntry = new RestfulAsrsSerachLog();
            logEntry.setRequestTime(new Date());

            // 对于批量请求，记录第一个条码作为标识
            if (requestData != null && requestData.getBarinfolist() != null && !requestData.getBarinfolist().isEmpty()) {
                logEntry.setBarinfo(requestData.getBarinfolist().get(0) + " (and " + (requestData.getBarinfolist().size() - 1) + " more)");
            }

            logEntry.setStatus(status);

            // 拼接 IP 和 User-Agent 到 successMessage 或 errorMessage
            String clientInfo = String.format("IP: %s", ipAddress);

            if ("success".equalsIgnoreCase(status)) {
                logEntry.setSuccessMessage("批量查询成功。" + clientInfo);
                if (responseDataList != null && !responseDataList.isEmpty()) {
                    // 记录查询结果数量
                    logEntry.setMaterialcode("Returned " + responseDataList.size() + " items");
                }
                logEntry.setErrorMessage(null); // 清空错误信息
            } else {
                logEntry.setSuccessMessage(null); // 错误时不设置成功信息
                logEntry.setErrorMessage(errorMsg + " [" + clientInfo + "]");
            }

            // 使用 service 插入日志
            restfulAsrsSerachLogService.save(logEntry);
        } catch (Exception e) {
            log.error("保存调用日志失败", e);
        }
    }





    // 获取客户端真实 IP（处理反向代理）
    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }



    @Data
    public static class RequestData {
        private String barinfo;
        private String plant;
    }

    // 在 RestfulAsrsController.java 中添加新的内部类

    @Data
    public static class BatchMinMaxRequestData {
        private List<String> barinfolist;
        private String plant;
    }

    @Data
    public static class BatchMinMaxResponseData {
        private String avpart;
        private String avdes1;
        private Integer v6maxq;
        private Integer v6minq;
        private Integer v6mpck;
        private String v6pctr;
        private String jodes1;
        // 新增的7参数构造函数（包含所有字段）
        public BatchMinMaxResponseData(String avpart, String avdes1, Integer v6maxq, Integer v6minq,
                                       Integer v6mpck, String v6pctr, String jodes1) {
            this.avpart = avpart;
            this.avdes1 = avdes1;
            this.v6maxq = v6maxq;
            this.v6minq = v6minq;
            this.v6mpck = v6mpck;
            this.v6pctr = v6pctr;
            this.jodes1 = jodes1;
        }
    }

    @Data
    public static class BatchMinMaxResponse {
        private String status;
        private String msg;
        private List<BatchMinMaxResponseData> data;

        public BatchMinMaxResponse(String status, String msg, List<BatchMinMaxResponseData> data) {
            this.status = status;
            this.msg = msg;
            this.data = data;
        }
    }


    @Data
    public static class ResponseData {
        private String materialcode;
        private String batchcode;
        private int number;
        private String createtime;
        private String desc;

        public ResponseData(String materialcode, String batchcode, int number, String createtime, String desc) {
            this.materialcode = materialcode;
            this.batchcode = batchcode;
            this.number = number;
            this.createtime = createtime;
            this.desc = desc;
        }
    }

    @Data
    public static class Response {
        private String status;
        private String msg;
        private ResponseData data;

        public Response(String status, String msg, ResponseData data) {
            this.status = status;
            this.msg = msg;
            this.data = data;
        }
    }
}
